iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
生成式 AI

30 天一人公司的 AI 開發實戰系列 第 19

Day 19: 開發工程師接任務:依據 Task 開工並檢驗完成,維護文件一致性

  • 分享至 

  • xImage
  •  

昨天談了如何撰寫完美的 Task 文件,但再完美的規劃,如果不能正確執行,也只是紙上談兵。

今天要分享的是我在一人公司中最重要的發現。

開發不只是寫程式,更是確保「想法、規劃、實作、文件」四者的一致性。

開發工程師的雙重身份

在一人公司中,我既是規劃者,也是執行者。這種雙重身份容易產生一個問題:

早上的我:「這個功能應該這樣做!」(寫下完美規劃)
下午的我:「算了,這樣比較快...」(偏離原始設計)
晚上的我:「我剛剛做了什麼?」(忘記更新文件)

這就是為什麼我需要一套嚴謹的執行流程。

接任務的標準流程

Step 1:理解任務

# 找到要執行的任務
$ ls docs/tasks/ | grep "developing"
0006_fr_database_migration_system.md  # 開發中

# 仔細閱讀任務文件
$ cat docs/tasks/0006_fr_database_migration_system.md

關鍵檢查點:理解背景和動機(Why)、明確技術方案(How)、清楚驗收標準(What)、了解測試要求(Test)。

Step 2:更新任務狀態

## 狀態
開發中  # 從規劃中改為開發中

## 更新歷程
- 2025-01-11:建立需求文件
- 2025-01-19:開始實作  # 新增今天日期

同時更新 docs/tasks/README.md

### 開發中

| 編號 | 任務名稱 | 類型 | 開始日期 | 負責人 | 進度 |
|------|----------|------|----------|---------|------|
| 0006 | 資料庫 Migration 系統 | FR | 2025-01-19 | Sam | 0% |

Step 3:環境準備

# 確保在正確的分支
git checkout -b feature/0006-database-migration

# 確認專案能正常建置
./gradlew clean build --no-daemon

# 執行現有測試確保基準正確
./gradlew allTests

執行開發:TIA 角色的介入

這時候,我會切換到一個特殊的角色:Technical Implementation Architect (TIA)。

什麼是 TIA?

TIA (Technical Implementation Architect) 是我定義的一個 AI 協作角色,專門負責確保技術計劃與實際實作的一致性。

想像一下,你規劃要用 SQLDelight 2.0,但專案實際用的是 2.1。你計劃把檔案放在 migrations/ 資料夾,但實際路徑應該是 shared/src/commonMain/sqldelight/migrations/。這些差異如果不及早發現,會導致實作時不斷碰壁。

TIA 就像是一個嚴謹的技術顧問,在你開始寫程式碼前,先幫你檢查計劃是否可行、與現實是否相符。

TIA 的第一次審查:計劃可行性

在開始寫程式碼前,TIA 會審查任務文件:

## TIA Review Report - Pre-Implementation

### Summary
- Task: 0006_fr_database_migration_system.md
- Review Date: 2025-01-19
- Status: 需要調整

### Identified Issues
1. **SQLDelight 版本差異**
   - Plan States: SQLDelight 2.0.0
   - Actual State: SQLDelight 2.1.0 (libs.versions.toml)
   - Correction: 更新文件使用 2.1.0 API
   - Impact: API 略有不同,需調整實作方式

2. **Migration 檔案位置**
   - Plan States: `migrations/` 
   - Actual State: 需要完整路徑 `shared/src/commonMain/sqldelight/migrations/`
   - Correction: 更新文件路徑
   - Impact: 避免建錯位置

實際開發過程

根據 TIA 的審查結果,開始實作:

// 1. 建立 MigrationHelper.kt
// 位置:shared/src/commonMain/kotlin/.../data/migration/
class MigrationHelper(private val databaseDriverFactory: DatabaseDriverFactory) {
    suspend fun initDatabase(): GrimoDatabase {
        val driver = databaseDriverFactory.createDriver()
        
        // TIA 提醒:SQLDelight 2.1.0 使用 awaitCreate 而非 await
        val currentVersion = getVersion(driver)
        if (currentVersion == 0L) {
            GrimoDatabase.Schema.awaitCreate(driver)
        } else if (currentVersion < GrimoDatabase.Schema.version) {
            GrimoDatabase.Schema.awaitMigrate(
                driver, 
                currentVersion, 
                GrimoDatabase.Schema.version
            )
        }
        
        return GrimoDatabase(driver)
    }
}

過程中的文件同步

每完成一個重要步驟,立即更新:

  1. Task 文件的進度更新
## 進度追蹤
- [x] 建立 MigrationHelper 類別
- [x] 實作版本檢查邏輯
- [ ] 撰寫 migration 檔案
- [ ] 整合到 DatabaseModule
- [ ] 撰寫單元測試
  1. 更新相關文件
# 更新資料庫設計文件
vim docs/architecture/database/migration-system.md

# 更新 CLAUDE.md 加入新的最佳實踐
vim CLAUDE.md

TIA 的第二次審查:實作驗證

完成初版後,TIA 再次介入:

## TIA Review Report - Implementation Validation

### Verified Components
- MigrationHelper 正確實作
- Migration 檔案格式正確
- 版本管理邏輯無誤

### 發現的問題
1. **缺少錯誤處理**
   - 問題:Migration 失敗時沒有 rollback
   - 建議:加入 try-catch 和錯誤日誌
   
2. **測試覆蓋不足**
   - 問題:只測試了 happy path
   - 建議:加入失敗場景測試

### 需要的文件更新
- [ ] 更新 developer-guide.md 加入 migration 流程
- [ ] 在 CLAUDE.md 加入 migration 檔案命名規範
- [ ] 更新 database_schema.md 記錄版本歷史

修正與完善

根據 TIA 的建議進行改進:

// 加入錯誤處理
class MigrationHelper(
    private val databaseDriverFactory: DatabaseDriverFactory,
    private val logger: Logger = createLogger<MigrationHelper>()
) {
    suspend fun initDatabase(): Result<GrimoDatabase> = runCatching {
        val driver = databaseDriverFactory.createDriver()
        
        try {
            // Migration 邏輯
            performMigration(driver)
            Result.success(GrimoDatabase(driver))
        } catch (e: Exception) {
            logger.error(e) { "Migration failed" }
            // 嘗試 rollback
            driver.close()
            Result.failure(e)
        }
    }
}

驗收檢查

回到原始 Task 文件的驗收標準。

功能性需求全部通過:新安裝能自動建立資料庫、舊版本能自動升級、Migration 失敗能 rollback、支援跳版本升級。

非功能性需求也大部分完成:Migration 執行時間實測只要 1.2 秒,錯誤訊息清楚明確,單元測試覆蓋率達到 85%。只剩文件更新還在進行中。

測試案例全部通過:Test_FirstInstall、Test_UpgradeV1toV3、Test_MigrationFailure、Test_DataIntegrity 都 PASSED。


## 完成任務:知識沉澱

### 1. 更新 Task 文件的「實作解決方案」

```markdown
## 實作解決方案

### 實際實作要點
1. **使用 SQLDelight 2.1.0 新 API**
   - awaitCreate() 取代 await()
   - 更簡潔的非同步處理

2. **錯誤處理策略**
   - 使用 Kotlin Result 類型
   - 失敗時自動關閉 driver
   - 完整的錯誤日誌

3. **測試策略**
   - 使用 in-memory 資料庫測試
   - 模擬各種 migration 場景
   - 驗證資料完整性

### 踩過的坑
1. **問題**:Migration 檔案命名必須是純數字
   **解決**:使用 1.sqm, 2.sqm 而非 v1.sqm

2. **問題**:測試時 migration 不執行
   **解決**:測試需要明確呼叫 migrate

### 效能優化
- Migration 使用 transaction 包裹
- 批次處理大量資料更新
- 適當的索引策略

2. 更新專案文件

提交前的文件檢查清單包括:Task 文件狀態改為「已完成」、docs/tasks/README.md 更新任務狀態、CLAUDE.md 加入新的開發規範、database_schema.md 更新 schema 版本、developer-guide.md 加入 migration 指南、更新 CHANGELOG.md。

文件一致性的維護技巧

1. 即時更新原則

我的工作習慣

開發 30 分鐘 → 更新文件 5 分鐘 → 繼續開發

2. Git Hook 自動檢查

#!/bin/bash
# .git/hooks/pre-commit

# 檢查是否有未更新的文件
if git diff --cached --name-only | grep -q "^src/"; then
    echo "記得更新相關文件:"
    echo "  - Task 文件進度"
    echo "  - CLAUDE.md(如有新規範)"
    echo "  - 相關設計文件"
fi

3. 文件驅動開發(SDD)

寫文件 → 寫測試 → 寫程式碼 → 更新文件

TIA 角色的價值

為什麼需要 TIA?

在一人公司中,你既是規劃者也是執行者。這很容易產生「當局者迷」的問題。你寫的計劃可能基於過時的記憶,或是理想化的假設。

TIA 角色的工作流程是這樣的:

  1. 審查計劃:檢查技術版本、檔案路徑、API 名稱是否正確
  2. 比對現況:實際查看專案檔案,確認與計劃的差異
  3. 識別問題:列出所有不一致的地方
  4. 修正計劃:更新錯誤的部分,讓計劃可執行
  5. 記錄決策:把重要的技術決定寫成文件

引入 TIA 角色後,我的開發品質顯著提升。

以前沒有 TIA 時,經常偏離原始設計,文件與程式碼脫節,重複踩相同的坑,技術債務不斷累積。

有了 TIA 之後,計劃與實作高度一致,文件始終保持更新,問題提前被發現,技術債務受到控制。

效果很明顯。計劃準確度大幅提升,Bug 率顯著降低,文件更新率達到 100%(因為強制檢查),重做時間大幅減少。

實用工具:輔助執行

1. Task 執行檢查腳本

#!/bin/bash
# check-task.sh

TASK_FILE=$1

echo "Task Execution Checklist"
echo "=========================="

# 檢查必要章節
grep -q "## 實作解決方案" $TASK_FILE || echo "Missing: 實作解決方案"
grep -q "已完成" $TASK_FILE && echo "Status: Completed"

# 檢查相關文件
echo "Related Documents:"
grep -o "docs/[^)]*" $TASK_FILE | sort -u

2. 進度追蹤儀表板

# 生成進度報告
echo "## Task Progress Report"
echo "Date: $(date +%Y-%m-%d)"
echo ""
echo "### Status Overview"
grep "## 狀態" docs/tasks/*.md | 
    cut -d: -f2 | sort | uniq -c

一人公司的特殊挑戰與解法

挑戰 1:角色切換困難

解法:使用不同的 Git 使用者

# 作為開發者
git config user.name "Developer"

# 作為 TIA 審查
git config user.name "TIA Reviewer"

挑戰 2:缺乏外部審查

解法:讓 AI 扮演 TIA

我:請以 TIA 角色審查我的實作,確認與專案實際狀況的一致性
Claude:我會檢查:
  1. 版本是否相符(libs.versions.toml vs 計劃)
  2. 檔案路徑是否正確
  3. API 名稱是否一致
  4. 資料庫 schema 是否匹配
  [產出審查報告]

挑戰 3:文件更新容易遺漏

解法:建立 Checklist 模板

## Commit Checklist
- [ ] Code 完成
- [ ] Test 通過
- [ ] Task 文件更新
- [ ] 相關文件同步
- [ ] CLAUDE.md 檢查

執行力 = 紀律 + 工具 + 流程

成功執行任務的關鍵不是技術能力。

而是紀律,嚴格遵循流程,不走捷徑。而是工具,TIA 角色、檢查腳本、自動化。而是流程,清晰的步驟、即時的文件更新。

對一人公司來說,這種「自我管理」的能力特別重要。你是自己的 PM、開發者、測試員、文件管理員。沒有外部監督,全靠自律。好的流程讓你不需要依賴記憶。TIA 角色幫你保持客觀。

優秀的執行不是完美的程式碼,而是可追溯、可維護、可演進的系統。

今日金句

「程式碼是暫時的,但決策和知識是永恆的。」

關於作者:Sam,一人公司創辦人。正在打造 Grimo,一個智能任務管理和分配平台。

專案連結GitHub - grimostudio


上一篇
Day 18: 系統設計師規劃任務:Task 的定義與撰寫
下一篇
Day 20: 架構師的決策記錄:為什麼選擇 MADR 來紀錄
系列文
30 天一人公司的 AI 開發實戰29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言